package com.atguigu.tingshu.common.aspect;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.anno.GuiguLogin;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import io.swagger.v3.core.util.Json;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Aspect         // 声明当前的类是一个切面类
@Component
public class GuiguLoginAspect {

    @Autowired
    RedisTemplate<String, String> redisTemplate;
    // 声明当前的方法就是一个环绕通知方法
    @Around(value = "@annotation(annotation))")
    public Object around(ProceedingJoinPoint point , GuiguLogin annotation) {

        //从HttpServletRequest中获取token  使用工具类
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("token");

        //获取required，如果是true则需要登录，如果是false则不需要登录
        boolean required = annotation.required();
        if (required) {
            //需要登录
            if (StringUtils.isEmpty(token)) {
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);//说明没登录
            }
            //token有值说明已经登录，根据从redis中查询数据
            String userInfoToken = redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX + token);
            if (StringUtils.isEmpty(userInfoToken)){
                //说明为未redis中查到对应的token，令牌已到期
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
            //把用户数据存储到ThreadLocal中
            UserInfo userInfo = JSON.parseObject(userInfoToken, UserInfo.class);
            AuthContextHolder.setUserId(userInfo.getId());
            AuthContextHolder.setUsername(userInfo.getNickname());
        }

        try {

            // 执行目标方法
            Object proceed = point.proceed();

            // 返回
            return proceed ;

        }catch (Throwable e) {
            e.printStackTrace();
        }finally {
            //清除ThreadLocal中数据
            AuthContextHolder.removeUserId();
            AuthContextHolder.removeUsername();
        }

        return null ;

    }

}